package com.ryskoo.permission.role.service;

import com.ryskoo.framework.core.bean.QueryMessageDTO;
import com.ryskoo.framework.core.service.BasicServiceImpl;
import com.ryskoo.framework.core.utils.DateFormatHelper;
import com.ryskoo.permission.manager.domain.ManagerPO;
import com.ryskoo.permission.manager.service.IManagerService;
import com.ryskoo.permission.managerrolerel.repository.IManagerRoleRelRepository;
import com.ryskoo.permission.menu.domain.MenuPO;
import com.ryskoo.permission.menu.service.IMenuService;
import com.ryskoo.permission.permission.domain.PermissionPO;
import com.ryskoo.permission.permission.service.IPermissionService;
import com.ryskoo.permission.role.domain.RolePO;
import com.ryskoo.permission.role.repository.IRoleRepository;
import com.ryskoo.permission.rolemenurel.domain.RoleMenuRelPO;
import com.ryskoo.permission.rolemenurel.repository.IRoleMenuRelRepository;
import com.ryskoo.permission.rolepermissionrel.domain.RolePermissionRelPO;
import com.ryskoo.permission.rolepermissionrel.repository.IRolePermissionRelRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Shawn
 */
@Service
public class RoleServiceImpl extends BasicServiceImpl<RolePO> implements IRoleService {
    @Autowired
    private IRoleRepository roleRepository;

    @PostConstruct
    public void init() {
        this.setDao(roleRepository);
    }

    @Autowired
    private IManagerService managerService;

    @Autowired
    private IPermissionService permissionService;

    @Autowired
    private IManagerRoleRelRepository managerRoleRelRepository;

    @Autowired
    private IMenuService menuService;

    @Autowired
    private IRoleMenuRelRepository roleMenuRelRepository;

    @Autowired
    private IRolePermissionRelRepository rolePermissionRelRepository;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdateRoleAndMenuAndPermission(RolePO role) {
        // 新增或者更新角色
        roleRepository.createOrUpdate(role);
        // 角色和菜单的关联关系
        List<RoleMenuRelPO> roleMenuRelList = new ArrayList<>();
        for (MenuPO menu : role.getMenuList()) {
            RoleMenuRelPO roleMenuRel = new RoleMenuRelPO();
            roleMenuRel.setRoleId(role.getUuid());
            roleMenuRel.setMenuId(menu.getUuid());
            roleMenuRel.setCreateTime(DateFormatHelper.getNowTimeStr());
            roleMenuRelList.add(roleMenuRel);

        }
        // 角色和权限的关联关系
        List<RolePermissionRelPO> rolePermissionRelList = new ArrayList<>();
        for (PermissionPO permission : role.getPermissionList()) {
            RolePermissionRelPO rolePermissionRel = new RolePermissionRelPO();
            rolePermissionRel.setRoleId(role.getUuid());
            rolePermissionRel.setPermissionId(permission.getUuid());
            rolePermissionRel.setCreateTime(DateFormatHelper.getNowTimeStr());
            rolePermissionRelList.add(rolePermissionRel);
        }
        // 删除已有的角色和菜单的关联关系
        roleMenuRelRepository.deleteRoleMenuRelByRoleId(role.getUuid());
        // 保存新的角色和菜单关联关系
        roleMenuRelRepository.batchCreate(roleMenuRelList);
        // 删除已有的角色和权限关联关系
        rolePermissionRelRepository.deleteRolePermissionRelByRoleId(role.getUuid());
        // 保存新的角色和权限关联关系
        rolePermissionRelRepository.batchCreate(rolePermissionRelList);
    }

    /**
     * 删除角色信息，支持批量删除
     * 同时还会删除角色与菜单的关联关系以及角色与权限的关联关系
     *
     * @param idList 要删除的角色id列表 {@link List}&lt;{@link String}&gt;
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRoleAndPermission(List<String> idList) {
        // 删除角色
        roleRepository.deletes(idList);
        for (String id : idList) {
            // 删除角色与菜单的关联关系
            roleMenuRelRepository.deleteRoleMenuRelByRoleId(id);
            // 删除角色与权限的关联关系
            rolePermissionRelRepository.deleteRolePermissionRelByRoleId(id);
        }
    }

    /**
     * 根据管理员id查询此管理员拥有的角色列表
     *
     * @param managerId 管理员id {@link String}
     * @return 管理员拥有的角色列表 {@link List}&lt;{@link RolePO}&gt;
     */
    @Override
    public List<RolePO> getRoleByManagerId(String managerId) {
        return roleRepository.getRoleByManagerId(managerId);
    }

    /**
     * 根据管理员用户名查询其关联的角色和权限
     *
     * @param userName
     * @return
     */
    @Override
    public List<RolePO> getRolesByManagerName(String userName) {
        List<RolePO> roles = new ArrayList<>();

        // 根据用户名查询管理员
        ManagerPO manager = managerService.getManagerByLoginName(userName);
        if (manager != null) {
            // 根据管理员查询关联的角色
            List<String> roleIds = managerRoleRelRepository.getRoleUuidsByManagerId(manager.getUuid());
            if (roleIds != null && roleIds.size() > 0) {
                for (String roleId : roleIds) {
                    RolePO role = roleRepository.getByUuid(roleId);
                    // 根据角色查询权限
                    List<PermissionPO> permissionList = permissionService.getPermissionByRoleId(roleId);
                    role.setPermissionList(permissionList);
                    roles.add(role);
                }
            }
        }
        return roles;
    }

    /**
     * 查询角色列表，包含角色所属权限
     *
     * @param qm 统一查询消息 {@link QueryMessageDTO}
     * @return 角色列表 {@link List}&lt;{@link RolePO}&gt;
     */
    @Override
    public List<RolePO> getRoleWithPermission(QueryMessageDTO qm) {
        List<RolePO> roleList = roleRepository.queryByCondition(qm, false);
        for (RolePO role : roleList) {
            role.setMenuList(menuService.getMenuByRoleId(role.getUuid(), 0));
            role.setPermissionList(permissionService.getPermissionByRoleId(role.getUuid()));
        }
        return roleList;
    }
}
